<?php

  class Char extends Base implements IChar {

    private $char;

    public function __construct($char) {
      if (is_string($char) && strlen($char) == 1) {
        $this->char = $char;
      } else {
        throw new IllegalArgumentException("\$char parameter must be a char.");
      }
    }

    /**
     * Checks if the internal char value equals the char value of the parameter $char.
     * @param IChar $char The char to compare to.
     * @return Boolean True on succes, false on failure.
     */
    public function equals(IChar $char = null) {
      if ($this->char === $char->charValue()) {
        return new Boolean(true);
      } else {
        return new Boolean(false);
      }
    }

    public function __invoke() {
      return $this->char;
    }

    public function isDigit(IChar $char = null) {
      $asciiValue = null;

      if (!is_null($char)) {
        $asciiValue = ord($char->toString());
      }
      return (($asciiValue > 47 && $asciiValue < 58) || ($asciiValue > 97 && $asciiValue < 122)) ? new Boolean(true) : new Boolean(false);
    }

    public function isLetter(IChar $char = null) {
      $asciiValue = null;

      if (!is_null($char)) {
        $asciiValue = ord($char->toString());
      }
      return (($asciiValue > 65 && $asciiValue < 90) || ($asciiValue > 96 && $asciiValue < 123)) ? new Boolean(true) : new Boolean(false);
    }

    public function isLetterOrDigit(IChar $char = null) {
      if (Char::isDigit($char)->booleanValue() || Char::isLetter($char)->booleanValue()) {
        return new Boolean(true);
      } else {
        return new Boolean(false);
      }
    }

    public function isLower(IChar $char = null) {
      $asciiValue = null;

      if (!is_null($char)) {
        $asciiValue = ord($char->toString());
      }
      return ($asciiValue > 96 && $asciiValue < 123) ? new Boolean(true) : new Boolean(false);
    }

    public function isPunctuation(IChar $char = null) {
      $asciiValue = null;

      if (!is_null($char)) {
        $asciiValue = ord($char->charValue());
      } else {
        $asciiValue = ord($this->char);
      }

      if ($asciiValue == 33 || $asciiValue == 46 || $asciiValue == 58 || $asciiValue == 59 || $asciiValue == 63) {
        return new Boolean(true);
      } else {
        return new Boolean(false);
      }
    }

    public function isUpper(IChar $char = null) {
      $asciiValue = null;

      if (!is_null($char)) {
        $asciiValue = ord($char->toString());
      }
      return ($asciiValue > 64 && $asciiValue < 91) ? new Boolean(true) : new Boolean(false);
    }

    public function isWhiteSpace(IChar $char = null) {
      return ord($char->toString()) == 32 ? new Boolean(true) : new Boolean(false);
    }

    /**
     *
     * @param type $char
     * @return Char
     */
    public static function parse($char) {
      if (is_string($char) && strlen($char) == 1) {
        return new Char($char);
      } else {
        throw new IllegalArgumentException("\$char parameter must be a char.");
      }
    }

    public function toLower(IChar $char = null) {
      if (!is_null($char)) {
        return new Char(strtolower($char->charValue()));
      } else {
        return new Char(strtolower($this->char));
      }
    }

    public function toString(IChar $char = null) {
      if (!is_null($char)) {
        return $char->toString();
      } else {
        return $this->char;
      }
    }

    public function toUpper(IChar $char = null) {
      if (is_null($char)) {
        return new Char(strtoupper($this->char));
      } else {
        return new Char(strtoupper($char->charValue()));
      }
    }

    /**
     * Returns the char value.
     * @return char The char value.
     */
    public function charValue() {
      return $this->char;
    }

  }

?>
